#include "actionmouse.h"
#include <QtGui>
#include <QtCore>
#include <QApplication>
#include <Windows.h>

enum ActionCode
{
    ACMouseDown = IAActDown, //只是按下
    ACMouseMove = IAActMove, //只是移动
    ACMouseUp = IAActUp,   //只是抬起
    AcMouseClick = IAActClick,   //单机
    AcMouseDouble = IAActDouble, //双击
    _TOTAL_ActionCode_
};

char descAc[][36]
{
    "MouseDown",
    "MouseMove",
    "MouseUp",
    "MouseClick",
    "MouseDouble",

    "exceed.."
};

ActionMouse::ActionMouse()
{
    classname = __FUNCTION__;
    actParam = QJsonObject();
}

ActionMouse::ActionMouse(InputAction action, const QPoint coordinator)
{
    classname = __FUNCTION__;
    actParam = QJsonObject();
    if(action >= _TOTAL_InputAction_ || action < 0) return;
    actParam.insert("action",(int)action);
    if(coordinator.isNull() == false){
        actParam.insert("pos-x",coordinator.x());
        actParam.insert("pos-y",coordinator.y());
    }
    syswidth = ::GetSystemMetrics(SM_CXSCREEN);
    sysheight = ::GetSystemMetrics(SM_CYSCREEN);
}

ExecuteRet ActionMouse::execute()
{
    ActionCode ac = (ActionCode) actParam.value("action").toInt();
    if(ac<0 || ac>=_TOTAL_ActionCode_){
        message = "illegal action code";
        return ERError;
    }
    INPUT input[4];
    memset(input,0,sizeof(INPUT)*4);
    int inputIndex = 0;
    DWORD timestamp = 1;
    QPoint oldPos = QCursor::pos();
    int x = actParam.value("pos-x").toInt(oldPos.x());
    int y = actParam.value("pos-y").toInt(oldPos.y());
    qInfo()<<classname<<"mouse"<<descAc[ac]<<"("<<x<<","<<y<<")";
    if(x<0 || y<0){
        message = "mouse pos invalid.";
        return ERError;
    }
    bool needMove = true;
    if(x == oldPos.x() && y == oldPos.y()){
        needMove = false;
    }

    if(needMove)
    {
        input[inputIndex].type = INPUT_MOUSE;
        input[inputIndex].mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE;
        input[inputIndex].mi.dx = x*65536/syswidth;
        input[inputIndex].mi.dy = y*65536/sysheight;
        input[inputIndex].mi.time = 0;
        ++inputIndex; timestamp+=100;
    }

    switch(ac)
    {
    case ACMouseDown:
    {
        input[inputIndex].type = INPUT_MOUSE;
        input[inputIndex].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
        input[inputIndex].mi.time = 0;
        ++inputIndex; timestamp+=100;
    }
        break;
    case ACMouseMove:
    {
        if(needMove == false){
            message = "move action with no coordinate.";
            return ERError;
        }
        needMove = false;  //不用归位啦.
    }
        break;
    case ACMouseUp:
    {
        input[inputIndex].type = INPUT_MOUSE;
        input[inputIndex].mi.dwFlags = MOUSEEVENTF_LEFTUP;
        input[inputIndex].mi.time = 0;
        ++inputIndex; timestamp+=100;
    }
        break;
    case AcMouseDouble:
    {
        input[inputIndex].type = INPUT_MOUSE;
        input[inputIndex].mi.dwFlags = MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP;
        input[inputIndex].mi.time = 0;
        ++inputIndex; timestamp+=100;
    }
        // don't break;
    case AcMouseClick:
    {
        input[inputIndex].type = INPUT_MOUSE;
        input[inputIndex].mi.dwFlags = MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP;
        input[inputIndex].mi.time = 0;
        ++inputIndex; timestamp+=100;
    }
        break;
    default:
    {
        qInfo()<<"unexpect action code:"<<ac;
    }
        break;
    }

    if(needMove)
    {
        input[inputIndex].type = INPUT_MOUSE;
        input[inputIndex].mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE;
        input[inputIndex].mi.dx = oldPos.x()*65536/syswidth;
        input[inputIndex].mi.dy = oldPos.y()*65536/sysheight;
        input[inputIndex].mi.time = 0;
        ++inputIndex; timestamp+=100;
    }

    Q_ASSERT(inputIndex<=4);
    SendInput(inputIndex,input,sizeof(INPUT));

    QThread::msleep(50);
    return ERSucc;
}
